#pragma once  // 防止头文件重复包含
//
// 包含必要的头文件
#include "Socket.hpp"      // 套接字相关功能
#include "TcpServer.hpp"   // TCP服务器实现
#include "Util.hpp"        // 工具函数
#include "Log.hpp"         // 日志功能
#include <iostream>        // 标准输入输出
#include <string>          // 字符串处理
#include <memory>          // 智能指针
#include <sstream>         // 字符串流
#include <functional>      // 函数对象
#include <unordered_map>   // 哈希表

using namespace SocketModule;  // 使用Socket模块命名空间
using namespace LogModule;     // 使用Log模块命名空间

// 定义HTTP协议中常用的分隔符常量
const std::string gspace = " ";        // 空格
const std::string glinespace = "\r\n"; // 行结束符
const std::string glinesep = ": ";     // 头部字段分隔符

// 定义Web根目录和默认页面
const std::string webroot = "./wwwroot";  // 网站根目录
const std::string homepage = "index.html"; // 默认首页
const std::string page_404 = "/404.html";  // 404错误页面

/**
 * @class HttpRequest
 * @brief HTTP请求类，用于解析和存储HTTP请求信息
 */
class HttpRequest
{
public:
    /**
     * @brief 构造函数，初始化交互标志为false
     */
    HttpRequest() : _is_interact(false) {}

    /**
     * @brief 序列化请求（暂未实现）
     * @return 返回空字符串
     */
    std::string Serialize()
    {
        return std::string();
    }

    /**
     * @brief 解析请求行
     * @param reqline 请求行字符串，格式如"GET / HTTP/1.1"
     */
    void ParseReqLine(std::string& reqline)
    {
        std::stringstream ss(reqline);  // 使用字符串流分割请求行
        ss >> _method >> _uri >> _version;  // 分别提取方法、URI和版本
    }

    /**
     * @brief 反序列化HTTP请求
     * @param reqstr 完整的HTTP请求字符串
     * @return 返回解析是否成功
     */
    bool Deserialize(std::string& reqstr)
    {
        // 1. 提取请求行
        std::string reqline;
        bool res = Util::ReadOneLine(reqstr, &reqline, glinespace);
        LOG(LogLevel::DEBUG) << reqline;

        // 2. 对请求行进行反序列化
        ParseReqLine(reqline);

        // 处理URI，添加webroot路径
        if (_uri == "/")
            _uri = webroot + _uri + homepage; // 访问根目录时指向首页
        else
            _uri = webroot + _uri; // 其他路径添加webroot前缀

        LOG(LogLevel::DEBUG) << "_method: " << _method;
        LOG(LogLevel::DEBUG) << "_uri: " << _uri;
        LOG(LogLevel::DEBUG) << "_version: " << _version;

        // 检查URI中是否包含查询参数
        const std::string temp = "?";
        auto pos = _uri.find(temp);
        if (pos == std::string::npos)
        {
            return true;  // 没有查询参数直接返回
        }

        // 分离URI和查询参数
        _args = _uri.substr(pos + temp.size());  // 提取参数部分
        _uri = _uri.substr(0, pos);             // 保留纯URI部分
        _is_interact = true;                     // 标记为交互请求

        return true;
    }

    // 获取URI
    std::string Uri() { return _uri; }

    // 检查是否是交互请求
    bool isInteract() { return _is_interact; }

    // 获取查询参数
    std::string Args() { return _args; }

    // 析构函数
    ~HttpRequest() {}

private:
    std::string _method;    // HTTP方法(GET/POST等)
    std::string _uri;       // 请求URI
    std::string _version;   // HTTP版本

    std::unordered_map<std::string, std::string> _headers;  // 请求头部
    std::string _blankline;  // 空行
    std::string _text;       // 请求体

    std::string _args;       // 查询参数
    bool _is_interact;       // 是否是交互请求标志
};

/**
 * @class HttpResponse
 * @brief HTTP响应类，用于构建和发送HTTP响应
 */
class HttpResponse
{
public:
    /**
     * @brief 构造函数，初始化版本和空行
     */
    HttpResponse() : _blankline(glinespace), _version("HTTP/1.0") {}

    /**
     * @brief 序列化HTTP响应
     * @return 返回完整的HTTP响应字符串
     */
    std::string Serialize()
    {
        // 构建状态行: HTTP/1.0 200 OK\r\n
        std::string status_line = _version + gspace + std::to_string(_code) + gspace + _desc + glinespace;

        // 构建响应头部
        std::string resp_header;
        for (auto& header : _headers)
        {
            std::string line = header.first + glinesep + header.second + glinespace;
            resp_header += line;
        }

        // 组合状态行、头部、空行和响应体
        return status_line + resp_header + _blankline + _text;
    }

    /**
     * @brief 设置目标文件路径
     * @param target 目标文件路径
     */
    void SetTargetFile(const std::string& target)
    {
        _targetfile = target;
    }

    /**
     * @brief 设置响应状态码
     * @param code HTTP状态码
     */
    void SetCode(int code)
    {
        _code = code;
        // 根据状态码设置描述
        switch (_code)
        {
        case 200:
            _desc = "OK";
            break;
        case 404:
            _desc = "Not Found";
            break;
        case 301:
            _desc = "Moved Permanently";
            break;
        case 302:
            _desc = "See Other";
            break;
        default:
            break;
        }
    }

    /**
     * @brief 添加响应头部
     * @param key 头部字段名
     * @param value 头部字段值
     */
    void SetHeader(const std::string& key, const std::string& value)
    {
        auto iter = _headers.find(key);
        if (iter != _headers.end()) return;  // 已存在则不重复添加
        _headers.insert(std::make_pair(key, value));
    }

    /**
     * @brief 根据文件后缀确定Content-Type
     * @param targetfile 目标文件名
     * @return 返回对应的MIME类型
     */
    std::string Uri2Suffix(const std::string& targetfile)
    {
        // 查找最后一个点号位置
        auto pos = targetfile.rfind(".");
        if (pos == std::string::npos)
        {
            return "text/html";  // 默认返回HTML类型
        }

        // 根据后缀返回对应MIME类型
        std::string suffix = targetfile.substr(pos);
        if (suffix == ".html" || suffix == ".htm")
            return "text/html";
        else if (suffix == ".jpg")
            return "image/jpeg";
        else if (suffix == "png")
            return "image/png";
        else
            return "";
    }

    /**
     * @brief 构建HTTP响应
     * @return 返回构建是否成功
     */
    bool MakeResponse()
    {
        // 特殊处理favicon.ico请求
        if (_targetfile == "./wwwroot/favicon.ico")
        {
            LOG(LogLevel::DEBUG) << "用户请求: " << _targetfile << "忽略它";
            return false;
        }

        // 重定向测试
        if (_targetfile == "./wwwroot/redir_test")
        {
            SetCode(301);
            SetHeader("Location", "https://www.qq.com/");
            return true;
        }

        // 读取文件内容
        int filesize = 0;
        bool res = Util::ReadFileContent(_targetfile, &_text);

        // 文件不存在处理
        if (!res)
        {
            _text = "";
            LOG(LogLevel::WARNING) << "client want get : " << _targetfile << " but not found";
            SetCode(404);
            _targetfile = webroot + page_404;  // 指向404页面
            filesize = Util::FileSize(_targetfile);
            Util::ReadFileContent(_targetfile, &_text);
            std::string suffix = Uri2Suffix(_targetfile);
            SetHeader("Content-Type", suffix);
            SetHeader("Content-Length", std::to_string(filesize));
        }
        else
        {
            // 文件存在正常处理
            LOG(LogLevel::DEBUG) << "读取文件: " << _targetfile;
            SetCode(200);
            filesize = Util::FileSize(_targetfile);
            std::string suffix = Uri2Suffix(_targetfile);
            SetHeader("Conent-Type", suffix);
            SetHeader("Content-Length", std::to_string(filesize));
            SetHeader("Set-Cookie", "username=zhangsan;");  // 设置Cookie
        }
        return true;
    }

    // 设置响应体文本
    void SetText(const std::string& t) { _text = t; }

    // 反序列化（暂未实现）
    bool Deserialize(std::string& reqstr) { return true; }

    // 析构函数
    ~HttpResponse() {}

public:  // 注意：这里应该是private，但原代码是public
    std::string _version;  // HTTP版本
    int _code;             // 状态码
    std::string _desc;     // 状态描述

    std::unordered_map<std::string, std::string> _headers;  // 响应头部
    std::vector<std::string> cookie;       // Cookie集合
    std::string _blankline;               // 空行
    std::string _text;                    // 响应体

    std::string _targetfile;              // 目标文件路径
};

// 定义HTTP处理函数类型
using http_func_t = std::function<void(HttpRequest& req, HttpResponse& resp)>;

/**
 * @class Http
 * @brief HTTP服务器类，处理HTTP请求和响应
 */
class Http
{
public:
    /**
     * @brief 构造函数，初始化TCP服务器
     * @param port 监听端口
     */
    Http(uint16_t port) : tsvrp(std::make_unique<TcpServer>(port)) {}

    /**
     * @brief 处理HTTP请求
     * @param sock 客户端套接字
     * @param client 客户端地址信息
     */
    void HandlerHttpRquest(std::shared_ptr<Socket>& sock, InetAddr& client)
    {
        // 接收HTTP请求
        std::string httpreqstr;
        int n = sock->Recv(&httpreqstr);  // 接收客户端请求

        if (n > 0)  // 接收到数据
        {
            std::cout << "##########################" << std::endl;
            std::cout << httpreqstr;
            std::cout << "##########################" << std::endl;

            // 解析请求并构建响应
            HttpRequest req;
            HttpResponse resp;
            req.Deserialize(httpreqstr);

            // 处理交互请求
            if (req.isInteract())
            {
                if (_route.find(req.Uri()) == _route.end())
                {
                    // 未注册的路由处理
                }
                else
                {
                    // 调用注册的处理函数
                    _route[req.Uri()](req, resp);
                    std::string response_str = resp.Serialize();
                    sock->Send(response_str);  // 发送响应
                }
            }
            else  // 处理静态资源请求
            {
                resp.SetTargetFile(req.Uri());
                if (resp.MakeResponse())
                {
                    std::string response_str = resp.Serialize();
                    sock->Send(response_str);
                }
            }
        }

        // 调试模式下的简化处理
#ifdef DEBUG
        std::string httpreqstr;
        sock->Recv(&httpreqstr);
        std::cout << httpreqstr;

        // 构建简单响应
        HttpResponse resp;
        resp._version = "HTTP/1.1";
        resp._code = 200;
        resp._desc = "OK";

        std::string filename = webroot + homepage;
        bool res = Util::ReadFileContent(filename, &(resp._text));
        (void)res;
        std::string response_str = resp.Serialize();
        sock->Send(response_str);
#endif
    }

    /**
     * @brief 启动HTTP服务器
     */
    void Start()
    {
        // 启动TCP服务器并设置回调函数
        tsvrp->Start([this](std::shared_ptr<Socket>& sock, InetAddr& client)
            { this->HandlerHttpRquest(sock, client); });
    }

    /**
     * @brief 注册服务路由
     * @param name 路由路径
     * @param h 处理函数
     */
    void RegisterService(const std::string name, http_func_t h)
    {
        std::string key = webroot + name;  // 构建完整路径
        auto iter = _route.find(key);
        if (iter == _route.end())
        {
            _route.insert(std::make_pair(key, h));  // 添加新路由
        }
    }

    // 析构函数
    ~Http() {}

private:
    std::unique_ptr<TcpServer> tsvrp;  // TCP服务器实例
    std::unordered_map<std::string, http_func_t> _route;  // 路由表
};